/*foodclerk.c*/
#include "cineplex.h"

void FoodClerk_Scheduler(int index)
{
	agentsStarted = agentsStarted + 1;
	Wait(initCond, initLock);
	foodClerks[index].runScheduler = runSchedulers;
	do
	{
		/*printf("%s hit scheduler\n",myName);*/
		Acquire(foodClerks[index].msgLock);
		if(foodClerks[index].status == TALKINGTOMANAGER)
		{
			/*if(msgList->Find("Okay"))*/
			FoodClerk_GetMessage(index, Okay);
			if(foodClerks[index].tempMsg.sender > -1)
			{
				FoodClerk_ContinueOn(index);
				Release(foodClerks[index].msgLock);
				continue;
			}
			
			/*else if(msgList->Find("GoOnBreak"))*/
			FoodClerk_GetMessage(index, GoOnBreak);
			if(foodClerks[index].tempMsg.sender > -1)
			{
				FoodClerk_GoOnBreak(index);
				Release(foodClerks[index].msgLock);
				continue;
			}
			/*else if(msgList->Find("ComeOffBreak"))*/
			FoodClerk_GetMessage(index, Okay);
			if(foodClerks[index].tempMsg.sender > -1)
			{
				FoodClerk_ComeOffBreak(index);
				Release(foodClerks[index].msgLock);
				continue;
			}
		}
		else if(foodClerks[index].status == WAITINGFORCUST)
		{
			/*msg=msgList->Find("WantPopcorn");*/
			FoodClerk_GetMessage(index, WantPopcorn);
			if(foodClerks[index].tempMsg.sender > -1)
			{
				FoodClerk_AcceptPopcornRequest(index, foodClerks[index].tempMsg.sender);
				Release(foodClerks[index].msgLock);
				continue;
			}
		}
		else if(foodClerks[index].status == WAITINGFORSODA)
		{
			/*msg=msgList->Find("WantSoda");*/
			FoodClerk_GetMessage(index, WantSoda);
			if(foodClerks[index].tempMsg.sender > -1)
			{
				FoodClerk_AcceptSodaRequest(index, foodClerks[index].tempMsg.sender);
				Release(foodClerks[index].msgLock);
				continue;
			}
		}
		else if(foodClerks[index].status == WAITINGFORPAY)
		{
			/*msg=msgList->Find("HereIsFoodMoney");*/
			FoodClerk_GetMessage(index, HereIsFoodMoney);
			if(foodClerks[index].tempMsg.sender > -1)
			{
				FoodClerk_GiveFood(index, foodClerks[index].tempMsg.sender);
				Release(foodClerks[index].msgLock);
				continue;
			}
		}
		else if(foodClerks[index].status == ONBREAK)
		{
			/*msg=msgList->Find("WhatIsStatus");*/
			FoodClerk_GetMessage(index, WhatIsStatus);
			if(foodClerks[index].tempMsg.sender > -1)
			{
				FoodClerk_TellStatus(index);
				Release(foodClerks[index].msgLock);
				continue;
			}
			/*msg=msgList->Find("GiveMeMoney");*/
			FoodClerk_GetMessage(index, Okay);
			if(foodClerks[index].tempMsg.sender > -1)
			{
				FoodClerk_GiveManagerMoney(index);
				Release(foodClerks[index].msgLock);
				continue;
			}
		}
		else if(foodClerks[index].status == IDLE)
		{
			/*msg=msgList->Find("WhatIsStatus");*/
			FoodClerk_GetMessage(index, WhatIsStatus);
			if(foodClerks[index].tempMsg.sender > -1)
			{
				FoodClerk_TellStatus(index);
				Release(foodClerks[index].msgLock);
				continue;
			}
			/*msg=msgList->Find("GiveMeMoney");*/
			FoodClerk_GetMessage(index, GiveMeMoney);
			if(foodClerks[index].tempMsg.sender > -1)
			{
				FoodClerk_GiveManagerMoney(index);
				Release(foodClerks[index].msgLock);
				continue;
			}
			else if(FoodClerk_CallNextInLine(index))
			{
				Release(foodClerks[index].msgLock);
				continue;
			}
		}
		Wait(foodClerks[index].sleepCon, foodClerks[index].msgLock);
	} while(foodClerks[index].runScheduler);
}

struct Message FoodClerk_GetMessage(int index, int name)
{
	/*this will be the null output*/
	foodClerks[index].tempMsg.name = NullMsg;
	foodClerks[index].tempMsg.sender = NullMsg;
	
	Acquire(loopLock);
	for(i = 0; i < foodClerks[index].numMsgs; i++)
	{
		if(foodClerks[index].msgList[i].name == name)
		{
			foodClerks[index].tempMsg.name = name;
			foodClerks[index].tempMsg.sender = foodClerks[index].msgList[i].sender;
			foodClerks[index].numMsgs = foodClerks[index].numMsgs - 1;
			break;
		}
	}
	for(k = i; k < 2; k++)
	{
		/*movin on up*/
		foodClerks[index].msgList[k].name = foodClerks[index].msgList[k+1].name;
		foodClerks[index].msgList[k].sender = foodClerks[index].msgList[k+1].sender;
	}
	foodClerks[index].msgList[2].name = NullMsg;
	foodClerks[index].msgList[2].sender = NullMsg;
	Release(loopLock);
		
	return foodClerks[index].tempMsg;
}

int FoodClerk_CallNextInLine(int index)
{
	Acquire(foodLinesLock);
	foodClerks[index].replyTo = foodLines[index].customers[0];
	if(foodClerks[index].replyTo != -1)
	{	
		/*printf("FoodClerk %s has a line length %i\n", myName, myLine->getSize()+1);*/
		ConsoleAcquire();
			Write("FoodClerk ", 10, ConsoleOutput);
			outputLen = Itoa(index, outBuff);
			Write(outBuff , outputLen, ConsoleOutput);
			Write(" has a line length ", 19, ConsoleOutput);
			outputLen = Itoa(Line_getSize(T_FOODCLERK,index), outBuff);
			Write(outBuff , outputLen, ConsoleOutput);
			Write("\n", 1, ConsoleOutput);
		ConsoleRelease();
		/*cust->SendMessage("ComeBuyTix",1,this);*/
		SendMessage(T_CUSTOMER, foodClerks[index].replyTo, ComeBuyFood, index);
		Release(foodLinesLock);
		foodClerks[index].status=WAITINGFORCUST;
		return 1;
	}
	Release(foodLinesLock);
	/*printf("FoodClerk %s has no one in line.  I am available for a customer\n", myName);*/
	ConsoleAcquire();
		Write("FoodClerk ", 10, ConsoleOutput);
		outputLen = Itoa(index, outBuff);
		Write(outBuff , outputLen, ConsoleOutput);
		Write(" has no one in line.  I am available for a customer\n", 52, ConsoleOutput);
	ConsoleRelease();
	return 0;
}

void FoodClerk_AcceptPopcornRequest(int index, int cust)
{
	foodClerks[index].popcornRequested=customers[cust].numPopcorn;
	/*cust->SendMessage("AnythingElse",1,this);*/
	SendMessage(T_CUSTOMER, cust, AnythingElse, index);
	foodClerks[index].status=WAITINGFORSODA;	
}

void FoodClerk_AcceptSodaRequest(int index, int cust)
{
	foodClerks[index].sodaRequested = customers[cust].numSoda;
	foodClerks[index].money = foodClerks[index].POPCORN_PRICE*foodClerks[index].popcornRequested + foodClerks[index].SODA_PRICE*foodClerks[index].sodaRequested;
	/*printf ("ConcessionClerk %s has an order for %i popcorn and %i soda. The cost is %.2f.\n",myName,popcornRequested,sodaRequested,money);*/
	ConsoleAcquire();
	Write("FoodClerk ", 12, ConsoleOutput);
	outputLen = Itoa(index, outBuff);
	Write(outBuff , outputLen, ConsoleOutput);
	Write(" has an order for ", 18, ConsoleOutput);
	outputLen = Itoa(foodClerks[index].popcornRequested, outBuff);
	Write(outBuff , outputLen, ConsoleOutput);
	Write(" popcorn and ", 13, ConsoleOutput);
	outputLen = Itoa(foodClerks[index].sodaRequested, outBuff);
	Write(outBuff , outputLen, ConsoleOutput);
	Write(" soda. The cost is $", 20, ConsoleOutput);
	outputLen = Itoa(foodClerks[index].money, outBuff);
	Write(outBuff , outputLen, ConsoleOutput);
	Write("\n", 1, ConsoleOutput);
	ConsoleRelease();
	/*cust->SendMessage("PayMeForFood",2,this,&money);*/
	SendMessage(T_CUSTOMER, cust, PayMeForFood, index);
	foodClerks[index].status = WAITINGFORPAY;	
}

void FoodClerk_GiveFood(int index, int cust)
{
	/*printf ("ConcessionClerk %s has been paid for the order\n",myName);*/
	ConsoleAcquire();
			Write("FoodClerk ", 10, ConsoleOutput);
			outputLen = Itoa(index, outBuff);
			Write(outBuff , outputLen, ConsoleOutput);
			Write(" has been paid for the order\n", 29, ConsoleOutput);
	ConsoleRelease();
	/*Popcorn* popcornPool = getCineplex()->popcornPool;
	Popcorn* popcorn = &(popcornPool[getCineplex()->popcornSold]);
	getCineplex()->popcornSold+=popcornRequested;*/ /*MBC*/
	
	/*Soda* sodaPool = getCineplex()->sodaPool;
	Soda* soda = &(sodaPool[getCineplex()->sodaSold]);
	getCineplex()->sodaSold+=sodaRequested;*/ /*MBC*/
		
	/*cust->SendMessage("HereIsYourFood",2,&popcorn,&soda);*/
	SendMessage(T_CUSTOMER, cust, HereIsYourFood, index);
	foodClerks[index].moneyCollected = foodClerks[index].moneyCollected + foodClerks[index].money;
	foodClerks[index].status=IDLE;
}

void FoodClerk_GiveManagerMoney(int index)
{
	/*manager->SendMessage("HereIsMoney",2,this,moneyCollected);*/
	SendMessage(T_MANAGER, 0, foodClerks[index].moneyCollected, index);
	/*moneyCollected=0.0f;*/ /*MBM*/
}

void FoodClerk_TellStatus(int index)
{
	if(foodClerks[index].status==ONBREAK)
	{
		foodClerks[index].onBreak=1;
	}
	else
	{
		foodClerks[index].onBreak=0;
	}
	
	/*manager->SendMessage("NumInLine",2,this,&lineLength);*/
	SendMessage(T_MANAGER, 0, NumInLine, index);
	foodClerks[index].status=TALKINGTOMANAGER;
}

void FoodClerk_ContinueOn(int index)
{
	if(foodClerks[index].onBreak)
	{
		foodClerks[index].status=ONBREAK;
	}
	else
	{
		foodClerks[index].status=IDLE;
	}
}

void FoodClerk_GoOnBreak(int index)
{
	/*printf("FoodClerk %s is going on break\n", myName);*/
	foodLines[index].isOpen=0;
	foodLines[index].length = -1;
	foodClerks[index].status=ONBREAK;
}

void FoodClerk_ComeOffBreak(int index)
{
	/*printf("FoodClerk %s is coming off break\n", myName);*/
	foodLines[index].isOpen=1;
	foodLines[index].length=0;
	foodClerks[index].status=IDLE;
}
